#include <windows.h>
#include <iostream>
#include <fstream>
#include <string>
#include <vector>
#include <tlhelp32.h>

#define STARTUP_PATH L".earlystart"  // 启动路径文件
#define LOG_FILE L"earlystart.log"    // 日志文件名
#define SERVICENAME L"EarlyStartService" // 服务名称宏定义

void MonitorLogin();
bool IsWinlogonRunning();
std::vector<std::wstring> ReadStartupPaths(const std::wstring& filePath);
void StartPrograms(const std::vector<std::wstring>& paths);
void LogMessage(const std::wstring& message);
void ServiceMain(DWORD argc, LPTSTR* argv);
void ServiceCtrlHandler(DWORD ctrlCode);

SERVICE_STATUS_HANDLE g_ServiceStatusHandle = NULL;
SERVICE_STATUS g_ServiceStatus = {0};

int main() {
    // 服务表条目
    SERVICE_TABLE_ENTRYW serviceTable[] = {  // 使用宽字符版本
            { const_cast<wchar_t*>(SERVICENAME), ServiceMain },  // 使用服务名称宏
            { NULL, NULL }
    };

    // 启动服务控制调度器
    if (!StartServiceCtrlDispatcher(serviceTable)) {
        return 1; // 启动失败
    }

    return 0; // 正常退出
}

void ServiceMain(DWORD argc, LPTSTR* argv) {
    g_ServiceStatusHandle = RegisterServiceCtrlHandlerW(SERVICENAME, ServiceCtrlHandler);

    g_ServiceStatus.dwServiceType = SERVICE_WIN32;
    g_ServiceStatus.dwCurrentState = SERVICE_START_PENDING;
    SetServiceStatus(g_ServiceStatusHandle, &g_ServiceStatus);

    LogMessage(L"Service is starting...");

    g_ServiceStatus.dwCurrentState = SERVICE_RUNNING;
    SetServiceStatus(g_ServiceStatusHandle, &g_ServiceStatus);

    MonitorLogin();

    g_ServiceStatus.dwCurrentState = SERVICE_STOPPED;
    SetServiceStatus(g_ServiceStatusHandle, &g_ServiceStatus);
}

void ServiceCtrlHandler(DWORD ctrlCode) {
    switch (ctrlCode) {
        case SERVICE_CONTROL_STOP:
            LogMessage(L"Service is stopping...");
            g_ServiceStatus.dwCurrentState = SERVICE_STOPPED;
            SetServiceStatus(g_ServiceStatusHandle, &g_ServiceStatus);
            break;
        default:
            break;
    }
}
void MonitorLogin() {
    while (true) {
        if (IsWinlogonRunning()) {
            LogMessage(L"Login detected successfully.");
            std::vector<std::wstring> startupPaths = ReadStartupPaths(STARTUP_PATH);
            StartPrograms(startupPaths);
            break;
        }
        Sleep(800);
    }
}

bool IsWinlogonRunning() {
    HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPALL, 0);
    if (hSnapshot == INVALID_HANDLE_VALUE) return false;

    PROCESSENTRY32W processEntry;
    processEntry.dwSize = sizeof(PROCESSENTRY32W);

    if (Process32FirstW(hSnapshot, &processEntry)) {
        do {
            if (_wcsicmp(processEntry.szExeFile, L"winlogon.exe") == 0) {
                CloseHandle(hSnapshot);
                return true;
            }
        } while (Process32NextW(hSnapshot, &processEntry));
    }
    CloseHandle(hSnapshot);
    return false;
}

std::vector<std::wstring> ReadStartupPaths(const std::wstring& filePath) {
    std::vector<std::wstring> paths;
    std::wifstream file(filePath.c_str());
    if (!file.is_open()) {
        LogMessage(L"Failed to open startup paths file: " + filePath);
        return paths;
    }

    std::wstring line;
    while (std::getline(file, line)) {
        if (!line.empty() && line[0] != L'#') {
            paths.push_back(line);
        }
    }

    LogMessage(L"Read " + std::to_wstring(paths.size()) + L" startup paths.");
    return paths;
}

void StartPrograms(const std::vector<std::wstring>& paths) {
    for (const auto& programPath : paths) {
        STARTUPINFOW si;
        PROCESS_INFORMATION pi;

        ZeroMemory(&si, sizeof(si));
        si.cb = sizeof(si);
        ZeroMemory(&pi, sizeof(pi));

        if (!CreateProcessW(programPath.c_str(), NULL, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi)) {
            LogMessage(L"Failed to start program: " + programPath + L" Error: " + std::to_wstring(GetLastError()));
        } else {
            CloseHandle(pi.hProcess);
            CloseHandle(pi.hThread);
            LogMessage(L"Started program: " + programPath);
        }
    }
}

void LogMessage(const std::wstring& message) {
    SYSTEMTIME st;
    GetLocalTime(&st);
    wchar_t timeBuffer[100];

    swprintf(timeBuffer, 100, L"[%04d-%02d-%02d %02d:%02d:%02d] %ls\n",
             st.wYear, st.wMonth, st.wDay, st.wHour, st.wMinute, st.wSecond, message.c_str());

    // 打印到控制台
    wprintf(L"%ls", timeBuffer);

    // 这里可以添加文件写入代码
}
